package com.itheima.service.impl;

import com.itheima.dao.MoneyLogDao;
import com.itheima.domain.MoneyLog;
import com.itheima.line.SessionThreadLocal;
import com.itheima.redission.DistributedLocker;
import com.itheima.redission.ZhzRedissonDistributedLocker;
import com.itheima.service.MoneyLogService;
import jodd.time.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/*****
 * @Author: http://www.itheima.com
 * @Description: com.itheima.service.impl.MoneyLogServiceImpl
 ****/
@Service
public class MoneyLogServiceImpl implements MoneyLogService {
    
    @Autowired
    private MoneyLogDao moneyLogDao;
    
    @Autowired
    private SessionThreadLocal sessionThreadLocal;
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private DistributedLocker distributedLocker;
    
    /***
     * 查询用户的抢红包记录
     * @return
     */
    @Override
    public List<MoneyLog> list() {
        //去缓存中找数据
        List<MoneyLog> moneyLogs = (List<MoneyLog>) redisTemplate.boundHashOps("UserMoneyLog").get(sessionThreadLocal.get().getUsername());
        if (moneyLogs != null) {
            return moneyLogs;
        }
        //查询数据
        moneyLogs = moneyLogDao.list(sessionThreadLocal.get().getUsername());
        
        //如果有数据，则将数据存入到Redis
        //if(moneyLogs!=null){
        //    redisTemplate.boundHashOps("UserMoneyLog").put(sessionThreadLocal.get().getUsername(),moneyLogs);
        //}
        redisTemplate.boundHashOps("UserMoneyLog").put(sessionThreadLocal.get().getUsername(), moneyLogs);
        return moneyLogs;
    }
    
    /***
     * 查询用户的抢红包记录
     * @param username
     * @return
     */
    @Override
    public List<MoneyLog> list(String username) {
        //查询数据
        return moneyLogDao.list(username);
    }
    
    /***
     * 获取排行数据
     */
    public List<MoneyLog> getTopList(String key) {
        Object moneyLogs = redisTemplate.boundHashOps("UserMoneyLog").get(key);
        if (moneyLogs != null) {
            return (List<MoneyLog>) moneyLogs;
        }
        return null;
    }
    
    /***
     * 添加红包记录
     * @param moneyLog
     * @return
     */
    @Override
    public int add(MoneyLog moneyLog) {
        return moneyLogDao.add(moneyLog);
    }
    
    /****
     * 抢红包排名信息
     * @return
     */
    @Override
    public List<MoneyLog> top() {
        String key = "MoneyLogTop100";
        //从缓存中后去数据
        Object mlogs = redisTemplate.boundValueOps(key).get();
        
        if (mlogs == null) {
            //控制用户操作，不要让所有用户直接操作数据库,获取锁
            Boolean bo = distributedLocker.lock("ITHEIMA", 10L, TimeUnit.SECONDS, 10L);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //拿到锁了，则查询数据库
            if (bo) {
                System.out.println("18082获取锁--" + simpleDateFormat.format(new Date()));
                mlogs = redisTemplate.boundValueOps(key).get();
                if (mlogs == null) {
                    //先从缓存中查找数据，缓存如果没有数据，则查询数据库
                    mlogs = moneyLogDao.top();
                    
                    //判断mlogs不为空，加入到缓存
                    if (mlogs != null) {
                        redisTemplate.boundValueOps(key).set(mlogs);
                        redisTemplate.expire(key, 1, TimeUnit.MINUTES);
                    }
                }
                //释放锁
                distributedLocker.unlock("ITHEIMA");
                System.out.println("18082释放锁--" + simpleDateFormat.format(new Date()));
            }
        }
        return (List<MoneyLog>) mlogs;
    }
    
    /****
     * 抢红包排名信息
     * @return
     */
    @Autowired
    private ZhzRedissonDistributedLocker zhzRedissonDistributedLocker;
    
    public List<MoneyLog> zhztop() {
        String key = "MoneyLogTop100";
        //从缓存中后去数据
        Object mlogs = redisTemplate.boundValueOps(key).get();
        if (mlogs == null) {
            Boolean isLock = zhzRedissonDistributedLocker.lock("ITHEIMA", 10L, TimeUnit.SECONDS, 10L);
            //需要加锁,
            if (isLock) {
                try {
                    //加锁成功
                    mlogs = redisTemplate.boundValueOps(key).get();
                    if (mlogs == null) {
                        // 如果缓存还是查不到,2到缓存中查询
                        mlogs = moneyLogDao.top();
                        if (mlogs != null) {
                            
                            redisTemplate.boundValueOps(key).set(mlogs);
                            redisTemplate.expire(key, 1, TimeUnit.MINUTES);
                        }
                    }                    
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    //如果查到了,就用缓存数据
                    //释放锁
                    zhzRedissonDistributedLocker.unlock(key);
                }
            }
        }
        return (List<MoneyLog>) mlogs;
    }
}
